#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
from lj_orm import tool_orm, orm
from lj_tool import tool_auth, tool_cache, tool_id, tool_time


@tool_cache.lj_wrapper_cache('lj-init-action-data')
# @tool_time.lj_time('LJ - 初始化ActionData')
def init_action_data(tname, ds_id='default'):
    return ActionData(tname, ds_id)


class ActionData():
    def __init__(self, tname, ds_id=None):
        self.tname = tname
        self.entity = orm.gen_model(tname, ds_id)
        self.primary = self.entity._meta.primary_key
        self.channel_id = ds_id

    def metadata(self):
        """
        元数据查询
        """
        return [tool_orm.transform_metadata({"name": name}) for name in self.entity.__dict__.keys()]

    def is_not_auto(self):
        return not self.primary.auto_increment or self.primary.auto_increment == False

    def sync(self, data):
        """
        数据同步
        """
        if not data.get(self.primary.name):
            if not self.primary.auto_increment or self.primary.auto_increment == False:
                data[self.primary.name] = tool_id.gen_id_str()
            print(f"LJ - 保存数据[{self.tname}][{data.get(self.primary.name)}]")
            data['created_by'] = data.get(
                'created_by', tool_auth.lj_auth_id())
            entity = self.entity(**data)
            entity.save(force_insert=True)
        else:
            print(f"LJ - 更新数据[{self.tname}][{data.get(self.primary.name)}]")
            # 执行更新语句
            self.entity.update(**data).where(self.primary ==
                                             data.get(self.primary.name)).execute()

        return data

    def remove(self, id):
        """
        数据删除,根据id删除
        """
        self.entity.delete().where(self.primary == id)

    def count(self, data={}):
        """
        查询数据数量
        """
        rules = self.transform(data.get('rules'))
        dataLevel = self.transformDataLevel(data.get('data_level'))
        return self.entity.select().where(rules & dataLevel).count()

    def get(self, id):
        try:
            return self.entity.get_or_none(getattr(self.entity, self.primary.name) == id)
        except:
            return None

    def list(self, data={}):
        """
        列表查询
        """
        rules = self.transform(data.get('rules'))
        dataLevel = self.transformDataLevel(data.get('data_level'))
        sorts = self.transformSorts(data.get('sorts'))
        return self.entity.select().where(rules & dataLevel).order_by(*sorts)

    def page(self, data={}):
        """
        分页查询
        """
        rules = self.transform(data.get('rules'))
        dataLevel = self.transformDataLevel(data.get('data_level'))
        page = data.get('page', {'page': 1, 'size': 18})
        sorts = self.transformSorts(data.get('sorts'))
        size = page.get('size')
        page_num = (page.get('page') - 1) * size

        datas = self.entity.select().limit(size).offset(
            page_num).where(rules & dataLevel).order_by(*sorts)
        count = self.entity.select().limit(size).offset(
            page_num).where(rules & dataLevel).count()
        return {
            'records': datas,
            'total': count
        }

    def transformSorts(self, orders=[]):
        """
        数据排序处理
        """
        resOrders = []
        if hasattr(self.entity, 'created_date'):
            resOrders.append(getattr(self.entity, 'created_date').desc())
        if not bool(orders):
            return resOrders
        if isinstance(orders, str):
            orders = json.loads(orders)
        for item in orders:
            if item.get('direction') == 'DESC':
                resOrders.append(
                    getattr(self.entity, item.get('field')).desc())
            elif item.get('direction') == 'ASC':
                resOrders.append(getattr(self.entity, item.get('field')).asc())
        return resOrders

    def transformDataLevel(self, level='public'):
        """
        数据级别处理
        """
        if level == 'public':
            return True
        elif level == 'only_my' and hasattr(self.entity, 'created_by'):
            return getattr(self.entity, 'created_by') == 0
        elif level == 'only_tenant' and hasattr(self.entity, 'tenant_id'):
            return getattr(self.entity, 'tenant_id') == 0
        return True

    def transform(self, rules):
        """
        转换制定规则的字符串为数据库筛选规则列表
        """
        res_rules_obj = True
        resRules = []
        if not rules or not self.entity:
            return res_rules_obj
        if isinstance(rules, str):
            rules = json.loads(rules)
        for key in rules:
            val = rules[key]
            keySpl = key.split('__')
            rule = keySpl[1]
            col = getattr(self.entity, keySpl[0])
            if rule == 'eq':
                resRules.append(col == val)
            elif rule == 'ne':
                resRules.append(col != val)
            elif rule == 'ge':
                resRules.append(col >= val)
            elif rule == 'gt':
                resRules.append(col > val)
            elif rule == 'le':
                resRules.append(col <= val)
            elif rule == 'lt':
                resRules.append(col < val)
            elif rule == 'like':
                resRules.append(col.like(val))
            elif rule == 'not_like':
                resRules.append(col.notlike(val))
            elif rule == 'in':
                resRules.append(col.in_(val))
            elif rule == 'not_in':
                resRules.append(~col.in_(val))
            elif rule == 'null':
                resRules.append(col.is_null())
            elif rule == 'not_null':
                resRules.append(col.is_not_null())
            elif rule == 'between':
                valSpl = val.split('__')
                resRules.append(col.between(valSpl[0], valSpl[1]))
            elif rule == 'not_between':
                pass

        for item in resRules:
            res_rules_obj = res_rules_obj & item

        return res_rules_obj
